/*
 * Copyright 2017-2024, Redis Ltd. and Contributors
 * All rights reserved.
 *
 * Licensed under the MIT License.
 */
package io.lettuce.core.cluster.api.async;

import java.util.Map;
import java.util.List;
import io.lettuce.core.VAddArgs;
import io.lettuce.core.VSimArgs;
import io.lettuce.core.annotations.Experimental;
import io.lettuce.core.json.JsonValue;
import io.lettuce.core.vector.RawVector;
import io.lettuce.core.vector.VSimScoreAttribs;
import io.lettuce.core.vector.VectorMetadata;

/**
 * Asynchronous executed commands on a node selection for Vector Sets
 * <p>
 * Vector sets are a Redis data type designed for storing and searching high-dimensional vectors. They support approximate
 * nearest neighbor search using the HNSW (Hierarchical Navigable Small World) algorithm.
 * <p>
 * Vector sets are particularly useful for machine learning applications, similarity search, recommendation systems, and other
 * use cases that involve high-dimensional vector data.
 *
 * @param <K> Key type.
 * @param <V> Value type.
 * @author Tihomir Mateev
 * @see <a href="https://redis.io/docs/latest/develop/data-types/vector-sets/">Redis Vector Sets</a>
 * @since 6.7
 * @generated by io.lettuce.apigenerator.CreateAsyncNodeSelectionClusterApi
 */
public interface NodeSelectionVectorSetAsyncCommands<K, V> {

    /**
     * Add a new element into the vector set specified by {@code key}.
     * <p>
     * By default, vectors are stored using int8 quantization for memory efficiency.
     * <p>
     * Time complexity: O(log(N)) for each element added, where N is the number of elements in the vector set.
     *
     * @param key the key of the vector set
     * @param element the name of the element that is being added to the vector set
     * @param vectors the vector values as floating point numbers
     * @return {@literal true} if the element was added, {@literal false} otherwise
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vadd/">Redis Documentation: VADD</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vadd(K key, V element, Double... vectors);

    /**
     * Add a new element into the vector set specified by {@code key} with the specified dimensionality.
     * <p>
     * This method allows implementing random projection to reduce the dimensionality of the vector. The projection matrix is
     * saved and reloaded along with the vector set.
     * <p>
     * Time complexity: O(log(N)) for each element added, where N is the number of elements in the vector set.
     *
     * @param key the key of the vector set
     * @param dimensionality the reduced number of dimensions for the vector
     * @param element the name of the element that is being added to the vector set
     * @param vectors the vector values as floating point numbers
     * @return {@literal true} if the element was added, {@literal false} otherwise
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vadd/">Redis Documentation: VADD</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vadd(K key, int dimensionality, V element, Double... vectors);

    /**
     * Add a new element into the vector set specified by {@code key} with additional options.
     * <p>
     * The {@link VAddArgs} allows configuring various options such as quantization type, exploration factor, and attributes.
     * <p>
     * Time complexity: O(log(N)) for each element added, where N is the number of elements in the vector set.
     *
     * @param key the key of the vector set
     * @param element the name of the element that is being added to the vector set
     * @param args the additional arguments for the VADD command
     * @param vectors the vector values as floating point numbers
     * @return {@literal true} if the element was added, {@literal false} otherwise
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vadd/">Redis Documentation: VADD</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vadd(K key, V element, VAddArgs args, Double... vectors);

    /**
     * Add a new element into the vector set specified by {@code key} with the specified dimensionality and additional options.
     * <p>
     * This method allows implementing random projection to reduce the dimensionality of the vector. The projection matrix is
     * saved and reloaded along with the vector set. Additional options could be specified via {@link VAddArgs}.
     * <p>
     * Time complexity: O(log(N)) for each element added, where N is the number of elements in the vector set.
     *
     * @param key the key of the vector set
     * @param dimensionality the reduced number of dimensions for the vector
     * @param element the name of the element that is being added to the vector set
     * @param args the additional arguments for the VADD command
     * @param vectors the vector values as floating point numbers
     * @return {@literal true} if the element was added, {@literal false} otherwise
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vadd/">Redis Documentation: VADD</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vadd(K key, int dimensionality, V element, VAddArgs args, Double... vectors);

    /**
     * Returns the number of elements in the vector set stored at {@code key}.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @return the number of elements in the vector set, or 0 if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vcard/">Redis Documentation: VCARD</a>
     */
    @Experimental
    AsyncExecutions<Long> vcard(K key);

    /**
     * Clears all attributes for the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return {@literal true} if the attributes were set, {@literal false} if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsetattr/">Redis Documentation: VSETATTR</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vClearAttributes(K key, V element);

    /**
     * Returns the dimensionality of the vector set stored at {@code key}.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @return the number of vector set elements
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vdim/">Redis Documentation: VDIM</a>
     */
    @Experimental
    AsyncExecutions<Long> vdim(K key);

    /**
     * Returns the approximate vector associated with a given {@code element} in the vector set stored at {@code key}.
     * <p>
     * Vector sets normalize and may quantize vectors on insertion. VEMB reverses this process to approximate the original
     * vector by de-normalizing and de-quantizing it. To retrieve the raw vector data, use {@link #vembRaw(K, V)}.
     * <p>
     * Time complexity: O(N) where N is the dimensionality of the vector
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return the vector values as a list of floating point numbers, or an empty list if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vemb/">Redis Documentation: VEMB</a>
     */
    @Experimental
    AsyncExecutions<List<Double>> vemb(K key, V element);

    /**
     * Returns the raw vector data for the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * This method returns the vector in its raw binary format, which can be more efficient for large vectors.
     * <p>
     * Time complexity: O(N) where N is the dimensionality of the vector
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return the raw vector data, or {@literal null} if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vemb/">Redis Documentation: VEMB</a>
     */
    @Experimental
    AsyncExecutions<RawVector> vembRaw(K key, V element);

    /**
     * Returns the attributes associated with the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * Attributes are stored as JSON and can contain any metadata associated with the vector element.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return the attributes as a JSON string, or {@literal null} if the key or element does not exist or has no attributes
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vgetattr/">Redis Documentation: VGETATTR</a>
     */
    @Experimental
    AsyncExecutions<String> vgetattr(K key, V element);

    /**
     * Returns the attributes associated with the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * Attributes are stored as JSON and can contain any metadata associated with the vector element.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return the attributes as a {@link JsonValue}, or {@literal null} if the key or element does not exist or has no
     *         attributes
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vgetattr/">Redis Documentation: VGETATTR</a>
     */
    @Experimental
    AsyncExecutions<List<JsonValue>> vgetattrAsJsonValue(K key, V element);

    /**
     * Returns metadata and internal details about the vector set stored at {@code key}.
     * <p>
     * The information includes details such as the number of elements, dimensionality, quantization type, and memory usage.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @return metadata about the vector set, or {@literal null} if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vinfo/">Redis Documentation: VINFO</a>
     */
    @Experimental
    AsyncExecutions<VectorMetadata> vinfo(K key);

    /**
     * Returns the neighbors of the specified {@code element} in the HNSW graph of the vector set stored at {@code key}.
     * <p>
     * Links represent connections to other elements in the graph structure used for similarity search.
     * <p>
     * Time complexity: O(M) where M is the maximum number of links per node
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return a list of elements that are linked to the specified element, or an empty list if the key or element does not
     *         exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vlinks/">Redis Documentation: VLINKS</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vlinks(K key, V element);

    /**
     * Returns the neighbors of the specified {@code element} in the HNSW graph along with their scores.
     * <p>
     * The scores represent the similarity between the specified element and its linked elements.
     * <p>
     * Time complexity: O(M) where M is the maximum number of links per node
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @return a list of elements with their similarity scores, or an empty list if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vlinks/">Redis Documentation: VLINKS</a>
     */
    @Experimental
    AsyncExecutions<Map<V, Double>> vlinksWithScores(K key, V element);

    /**
     * Returns a random element from the vector set stored at {@code key}. This command is useful for sampling elements for
     * testing or training or generating random queries for performance testing.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @return a random element from the vector set, or an empty list if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vrandmember/">Redis Documentation: VRANDMEMBER</a>
     */
    @Experimental
    AsyncExecutions<V> vrandmember(K key);

    /**
     * Returns multiple random elements from the vector set stored at {@code key}. This command is useful for sampling elements
     * for testing or training or generating random queries for performance testing.
     * <p>
     * <ul>
     * <li>When called with a positive count, returns up to that many distinct elements (no duplicates).</li>
     * <li>When called with a negative count, returns that many elements, possibly with duplicates.</li>
     * <li>If the count exceeds the number of elements, the entire set is returned.</li>
     * </ul>
     * Time complexity: O(count)
     *
     * @param key the key of the vector set
     * @param count the number of random elements to return
     * @return a list of random elements from the vector set, or an empty list if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vrandmember/">Redis Documentation: VRANDMEMBER</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vrandmember(K key, int count);

    /**
     * Removes the specified {@code element} from the vector set stored at {@code key}.
     * <p>
     * VREM reclaims memory immediately. It does not use tombstones or logical deletions, making it safe to use in long-running
     * applications that frequently update the same vector set. Time complexity: O(log(N)) where N is the number of elements in
     * the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element to remove from the vector set
     * @return {@literal true} if the element was removed, {@literal false} if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vrem/">Redis Documentation: VREM</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vrem(K key, V element);

    /**
     * Sets or updates the attributes for the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * Attributes are stored as JSON and can contain any metadata associated with the vector element. You can also update
     * existing attributes or delete them by setting an empty string.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @param json the attributes as a JSON string
     * @return {@literal true} if the attributes were set, {@literal false} if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsetattr/">Redis Documentation: VSETATTR</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vsetattr(K key, V element, String json);

    /**
     * Sets or updates the attributes for the specified {@code element} in the vector set stored at {@code key}.
     * <p>
     * Attributes are stored as JSON and can contain any metadata associated with the vector element. You can also update
     * existing attributes or delete them by setting an empty string.
     * <p>
     * Time complexity: O(1)
     *
     * @param key the key of the vector set
     * @param element the name of the element in the vector set
     * @param json the attributes as a {@link JsonValue} object
     * @return {@literal true} if the attributes were set, {@literal false} if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsetattr/">Redis Documentation: VSETATTR</a>
     */
    @Experimental
    AsyncExecutions<Boolean> vsetattr(K key, V element, JsonValue json);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key}.
     * <p>
     * This method performs a similarity search using the HNSW algorithm.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param vectors the query vector values as floating point numbers
     * @return a list of elements most similar to the query vector, or an empty list if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vsim(K key, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key}.
     * <p>
     * This method performs a similarity search using the vector of an existing element as the query.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @return a list of elements most similar to the specified element, or an empty list if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vsim(K key, V element);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key} with additional options.
     * <p>
     * The {@link VSimArgs} allows configuring various options such as the number of results, exploration factor, and filtering.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param args the additional arguments for the VSIM command
     * @param vectors the query vector values as floating point numbers
     * @return a list of elements most similar to the query vector, or an empty list if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vsim(K key, VSimArgs args, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key} with additional
     * options.
     * <p>
     * This method combines using an existing element's vector as the query with the ability to specify additional options via
     * {@link VSimArgs}.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @param args the additional arguments for the VSIM command
     * @return a list of elements most similar to the specified element, or an empty list if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<List<V>> vsim(K key, VSimArgs args, V element);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key} and returns them with
     * their similarity scores.
     * <p>
     * The similarity scores represent the distance between the query vector and the result vectors.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param vectors the query vector values as floating point numbers
     * @return a map of elements to their similarity scores, or an empty map if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, Double>> vsimWithScore(K key, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key} and returns them
     * with their similarity scores.
     * <p>
     * The similarity scores represent the distance between the specified element's vector and the result vectors.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @return a map of elements to their similarity scores, or an empty map if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, Double>> vsimWithScore(K key, V element);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key} with additional options
     * and returns them with their similarity scores.
     * <p>
     * The {@link VSimArgs} allows configuring various options such as the number of results, exploration factor, and filtering.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param args the additional arguments for the VSIM command
     * @param vectors the query vector values as floating point numbers
     * @return a map of elements to their similarity scores, or an empty map if the key does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, Double>> vsimWithScore(K key, VSimArgs args, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key} with additional
     * options and returns them with their similarity scores.
     * <p>
     * This method combines using an existing element's vector as the query with the ability to specify additional options via
     * {@link VSimArgs}.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @param args the additional arguments for the VSIM command
     * @return a map of elements to their similarity scores, or an empty map if the key or element does not exist
     * @since 6.7
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, Double>> vsimWithScore(K key, VSimArgs args, V element);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key} and returns them with
     * their similarity scores and attributes.
     * <p>
     * The similarity scores represent the distance between the query vector and the result vectors. Attributes are returned as
     * a server-provided string.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param vectors the query vector values as floating point numbers
     * @return a map of elements to their (score, attributes), or an empty map if the key does not exist
     * @since 7.0
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, VSimScoreAttribs>> vsimWithScoreWithAttribs(K key, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key} and returns them
     * with their similarity scores and attributes.
     * <p>
     * The similarity scores represent the distance between the specified element's vector and the result vectors. Attributes
     * are returned as a server-provided string.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @return a map of elements to their (score, attributes), or an empty map if the key or element does not exist
     * @since 7.0
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, VSimScoreAttribs>> vsimWithScoreWithAttribs(K key, V element);

    /**
     * Finds the most similar vectors to the given query vector in the vector set stored at {@code key} with additional options
     * and returns them with their similarity scores and attributes.
     * <p>
     * The {@link VSimArgs} allows configuring various options such as the number of results ({@code COUNT}), epsilon cutoff
     * ({@code EPSILON}), exploration factor ({@code EF}), and filtering.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param args the additional arguments for the VSIM command
     * @param vectors the query vector values as floating point numbers
     * @return a map of elements to their (score, attributes), or an empty map if the key does not exist
     * @since 7.0
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, VSimScoreAttribs>> vsimWithScoreWithAttribs(K key, VSimArgs args, Double... vectors);

    /**
     * Finds the most similar vectors to the given element's vector in the vector set stored at {@code key} with additional
     * options and returns them with their similarity scores and attributes.
     * <p>
     * This method combines using an existing element's vector as the query with the ability to specify additional options via
     * {@link VSimArgs}. Attributes are returned as a server-provided string.
     * <p>
     * Time complexity: O(log(N)) where N is the number of elements in the vector set
     *
     * @param key the key of the vector set
     * @param element the name of the element whose vector will be used as the query
     * @param args the additional arguments for the VSIM command
     * @return a map of elements to their (score, attributes), or an empty map if the key or element does not exist
     * @since 7.0
     * @see <a href="https://redis.io/docs/latest/commands/vsim/">Redis Documentation: VSIM</a>
     */
    @Experimental
    AsyncExecutions<Map<V, VSimScoreAttribs>> vsimWithScoreWithAttribs(K key, VSimArgs args, V element);

}
